package com.chaos.auth.config.grant.converter;


import cn.hutool.core.util.ObjectUtil;
import com.chaos.auth.config.grant.converter.para.AppOpenIdOAuth2ParameterNames;
import com.chaos.auth.config.grant.grant.GrantType;
import com.chaos.auth.config.grant.converter.helper.OAuth2EndpointHelper;
import com.chaos.auth.config.grant.token.AppOpenIdAuthenticationToken;
import com.chaos.framework.model.enums.ResultEnum;
import jakarta.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.core.OAuth2ErrorCodes;
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
import org.springframework.security.web.authentication.AuthenticationConverter;
import org.springframework.util.MultiValueMap;

import java.util.HashMap;
import java.util.Map;

public class AppOpenIdAuthenticationConverter implements AuthenticationConverter {
    @Override
    public Authentication convert(HttpServletRequest request) {
        String grantType = request.getParameter(OAuth2ParameterNames.GRANT_TYPE);
        if (!GrantType.OPEN_ID.getValue().equals(grantType)) {
            return null;
        }
        Authentication clientPrincipal = SecurityContextHolder.getContext().getAuthentication();
        MultiValueMap<String, String> parameters = OAuth2EndpointHelper.getParameters(request);

        String code = parameters.getFirst(AppOpenIdOAuth2ParameterNames.CODE);
        if (StringUtils.isEmpty(code)) {

            OAuth2EndpointHelper.throwError(ResultEnum.INVALID_REQUEST.getCode(), ResultEnum.INVALID_REQUEST.getMsg() + ":" + OAuth2ParameterNames.CODE);
        }
        String tenantId = parameters.getFirst(AppOpenIdOAuth2ParameterNames.TENANT_ID);
        if (StringUtils.isEmpty(tenantId)) {
            OAuth2EndpointHelper.throwError(ResultEnum.INVALID_REQUEST.getCode(), ResultEnum.INVALID_REQUEST.getMsg() + ":" + AppOpenIdOAuth2ParameterNames.TENANT_ID);
        }
        String referrer = parameters.getFirst(AppOpenIdOAuth2ParameterNames.REFERRER);
        String source = parameters.getFirst(AppOpenIdOAuth2ParameterNames.SOURCE);


        Map<String, Object> additionalParameters = new HashMap<>();
        parameters.forEach((key, value) -> {
            if (!key.equals(OAuth2ParameterNames.GRANT_TYPE) &&
                    !key.equals(OAuth2ParameterNames.CLIENT_ID) &&
                    !key.equals(OAuth2ParameterNames.USERNAME) &&
                    !key.equals(OAuth2ParameterNames.PASSWORD)) {
                additionalParameters.put(key, value.get(0));
            }
        });
        if (ObjectUtil.isNotEmpty(tenantId)) {
            additionalParameters.put(AppOpenIdOAuth2ParameterNames.TENANT_ID, Long.parseLong(tenantId));
        }
        if (ObjectUtil.isNotEmpty(referrer)) {
            additionalParameters.put(AppOpenIdOAuth2ParameterNames.REFERRER, Long.parseLong(referrer));
        }
        additionalParameters.put(AppOpenIdOAuth2ParameterNames.SOURCE, source);

        return new AppOpenIdAuthenticationToken(code, clientPrincipal, additionalParameters);

    }
}